from jsonrpcclient.clients.http_client import HTTPClient
from jsonrpcclient.exceptions import ReceivedNon2xxResponseError, ReceivedErrorResponseError

import logging
from django.conf import settings

def init_logger():
    LOG_FORMATTER = '[%(asctime)s] %(levelname)-8s %(pathname)s %(funcName)s %(lineno)d s %(trace_id)s : %(message)s'  # noqa
    filepath = '/data/log/rpc_test.log'

    logger = logging.getLogger('jsonrpcclient.client.request')
    logger.setLevel(logging.DEBUG)

    formatter = logging.Formatter(LOG_FORMATTER)
    fh = logging.FileHandler(filepath)
    fh.setFormatter(formatter)
    logger.addHandler(fh)

    logger = logging.getLogger('jsonrpcclient.client.response')
    logger.setLevel(logging.DEBUG)
    formatter = logging.Formatter(LOG_FORMATTER)
    fh = logging.FileHandler(filepath)
    fh.setFormatter(formatter)
    logger.addHandler(fh)
    return logger


logger = init_logger()


clients = list([HTTPClient(url) for url in settings.TEST_RPC_SERVERS])


rr = 0  # 自增计数
down = -1  # 暂时不可用节点标示
down_rr = -1  # 不可用节点挂掉时候 rr计数


def set_down(_down):
    global down, down_rr, rr
    down = _down
    down_rr = rr


def reset_down():
    global down
    set_down(-1)


def get_client():
    '''
    获取 rpc 客户端
    :return:
    '''
    global rr, down, down_rr
    rr += 1
    if down >= 0 and (rr % len(settings.TEST_RPC_SERVERS) == down):  # 计数==暂时不可以节点， 跳过此节点
        rr += 1
        if rr - down_rr > 1000:  # 尝试
            reset_down()

    index = rr % len(settings.TEST_RPC_SERVERS)
    return clients[index], index


class RpcClient():  # 支持重试一次
    def __getattr__(self, item):

        def attr_handler(*args, **kwargs):
            res = None
            for ii in range(2):
                try:
                    client, index = get_client()
                    res = getattr(client, item)(*args, **kwargs)
                    break
                except ReceivedNon2xxResponseError as e:
                    logger.error('%s, %s', e, 'ReceivedNon2xxResponseError')
                    break
                except ReceivedErrorResponseError as e:
                    logger.error('%s, %s', e, 'ReceivedErrorResponseError')
                    break
                except Exception as e:
                    set_down(index)
                    continue
            return res.data.result

        return attr_handler


rpc_client = RpcClient()  # rpc_client 实例
